package base;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import utilitarios.Bean;
import javax.faces.event.ActionEvent;



/**
 * Formulario Bean do caso de uso - Cadastro Simples.
 * @author Fernando Franzini
 * @author Edson Bernardo
 */

public abstract class ListaDetalhe<M> extends FormularioBase {
	
	protected static enum Acao {INSERIR, ALTERAR}
	protected static final String LISTA = "LISTA";
	protected static final String DETALHE = "DETALHE";
	private static NumberFormat nf = NumberFormat.getCurrencyInstance(new Locale("pt","BR"));
	
	protected Acao acao;
	protected List<M> colecao;
	protected String coluna;
	protected boolean ascending;
	protected StringBuffer jsCaptutar;
	//** Utilizados no controle da pagina��o. **/
	protected int inicio = 0;
	protected int paginaAtual = 0;
	protected int paginaTotal = 0;
	protected final int paginacao = 50;

	public ListaDetalhe() {
		jsCaptutar = new StringBuffer();
		colecao = new ArrayList<M>();
		coluna = "";
	}

	protected void limparJsCapturar() {
		jsCaptutar.delete(0, jsCaptutar.length());
	}

	/**Utilizado para retirar os caracteres de mascaras  */
	protected final String retirarMascara(String campo, char... mascara) {
		for (int cont = 0; cont < mascara.length; cont++) {
			campo = campo.replace("" + mascara[cont], "");
		}

		String saida = "";
		for (int cont = 0; cont < campo.length(); cont++) {
			if (campo.charAt(cont) != ' ') {
				saida += campo.charAt(cont);
			}
		}

		return saida.toString();
	}
	
	/**Utilizado para retirar mascara de valores double   */
	protected final String retirarMascaraValor(String campo, char... mascara) {
		
		String saida = retirarMascara(campo, mascara);
		saida = saida.replace(',', '.');
	
		return saida;
	}
	
	
	/**
	 * Chamado por outras telas que precisem capturar.
	 * Utilizado para receber o parametros e montar o javascript de captura.
	 */
	public void paramNavegacao(ActionEvent event) {
		String form = getParametrosRequest("formulario");
		String id = getParametrosRequest("campoId");
		String codigo = getParametrosRequest("campoCodigo");
		String desc = getParametrosRequest("campoDesc");
		limparJsCapturar();
		jsCaptutar
				.append("function capturar(campoId,campoCodigo,campoDesc){\n\t try {\n");
		if (id != null) {
			jsCaptutar.append("\t opener.document.forms['" + form + "']['" + id
					+ "'].value=campoId;\n");
		}
		if (codigo != null) {
			jsCaptutar.append("\t opener.document.forms['" + form + "']['"
					+ codigo + "'].value=campoCodigo;\n");
		}
		if (desc != null) {
			jsCaptutar.append("\t opener.document.forms['" + form + "']['"
					+ desc + "'].value=campoDesc;\n");
		}
		jsCaptutar.append("\t }finally{ \n\twindow.close();}}");
	}

	/**
	 * Utilizado para colocar mascaras em campos, seguindo um determinado padrão.
	 * @param campo String a ser formatada.
	 * @param padrao Padrão de configuração - Utilize o '#'. Exemplo: ##-##(##).
	 * @return String como o campo formatado.
	 */
	public String setMascara(String campo, String padrao) {
		if (campo == null) {
			throw new IllegalArgumentException(
					"Campo para formatação não pode ser null.");
		}
		if (campo.trim().equals("")) {
			return campo;
		}
		if (padrao == null || campo.trim().equals("")) {
			throw new IllegalArgumentException(
					"Mascara padrão não pode ser null ou vazio.");
		}
		if (!padrao.contains("#")) {
			throw new IllegalArgumentException(
					"Mascara padrão deve possuir caractere(s) '#' para "
							+ "definir a mascara.");
		}
		String templates = padrao.replace("#", "");
		campo = retirarMascara(campo, templates.toCharArray());
		String r = "";
		char[] p = padrao.toCharArray();
		char[] c = campo.toCharArray();
		try {
			for (int iP = 0, iC = 0, i = 0; i < p.length; ++i, ++iP) {
				if (p[i] == '#') {
					// acrescenta o campo.
					r += c[iC];
					++iC;
					continue;
				} else {
					// acrescenta a mascara.
					r += p[iP];
					continue;
				}
			}
		} catch (Exception e) {
			// So vai acontecer exception se o conteudo do campo for MENOR
			// que os valores das mascaras '#' definido.
		}
		return r;
	}

	/**
     * Utilizado para formatar mascara de valores ..#.###.###,##.
     * @param campo String a ser formatado.
     * @return Valor do campo formatado.
     */
    public static String setMascaraValor(String campo) {
		if (campo == null) {
			throw new IllegalArgumentException(
					"Campo para formatação não pode ser null.");
		}
		if (campo.trim().equals("")) {
			return campo;
		}
		BigDecimal bd;
		try {
			bd = new BigDecimal(campo);
		} catch (Exception e) {
			System.out.println("Erro em mascara de dinheiro no valor: " + campo);
			return campo;
		}
		String vl = nf.format(bd);
		return vl.replace("R$ ", "");
	} 

	
	// Metodos de ordena��o da listas.

	public final void setarColuna(ActionEvent e) {
		String colunaOrdenar = this.getParametrosRequest("coluna");
		if (colunaOrdenar == null) {
			throw new IllegalArgumentException(
					"Nome da coluna de ordenação obrigatoria.");
		}
		if (coluna.equals(colunaOrdenar)) {
			//current sort equals new sortColumn -> reverse sort order
			ascending = !ascending;
		} else {
			//sort new column in default direction
			ascending = true;
		}
		coluna = colunaOrdenar;
	}

	public final void ordenarPorColuna() {
		if (coluna == null || getColecao() == null) {
			return;
		}
		sort(coluna, ascending);
	}

	public void atualizarElemento(M novo) {
		int i = colecao.indexOf(novo);
		M velho = colecao.get(i);
		try {
                   Bean.copiarPropriedades(velho, i);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public abstract void sort(final String column, final boolean ascending);

	// get's e set's'

	public final Acao getAcao() {
		return acao;
	}

	public final void atualizarLista(M[] lista) {
		colecao.clear();
		for (M item : lista) {
			colecao.add(item);
		}
	}

	public final List<M> getColecao() {
		return colecao;
	}

	public void setColuna(String c) {
		coluna = c;
	}

	public String getColuna() {
		return coluna;
	}

	public final String getscriptCapturar() {
		if (jsCaptutar.length() == 0) {
			jsCaptutar.append("function capturar(){window.close();}");
		}
		return jsCaptutar.toString();
	}

	//PAGINA��O DE LISTAS

	 /*****************************************
		Controle de Paginação das Listas
	 *****************************************/

	/** Coloca o foco da paginação na primeira pagina. **/
	public void primeiro() {
		if (colecao.size() > 0) {
			inicio = 0;
			paginaAtual = 1;
		} else {
			paginaAtual = 0;
		}
	}

	/** Coloca o foco da paginação na ultima pagina. **/
	public void ultimo() {
		int pagina = 0;
		int total = colecao.size() - 1;
		while (true) {
			pagina += paginacao;
			if (pagina > total) {
				pagina -= paginacao;
				break;
			}
		}
		inicio = pagina;
		paginaAtual = paginaTotal;
	}

	/** Coloca o foco da paginação na proxima pagina. **/
	public void proximo() {
		int size = colecao.size();
		if (inicio < (size - paginacao)) {
			inicio = inicio + paginacao;
			paginaAtual++;
		}
	}

	/** Coloca o foco da paginação na pagina anterior. **/
	public void anterior() {
		if (inicio > paginacao - 1) {
			inicio = inicio - paginacao;
			paginaAtual--;
		}
	}

	/** Utilizado para calcular o numero de paginações da lista do modelo. **/
	protected void calcularTotalPaginas(int total) {
		paginaTotal = 0;
		int controle = 0;
		while (true && total > 0) {
			paginaTotal++;
			controle = paginaTotal * paginacao;
			if (controle < total) {
				continue;
			} else if (controle >= total) {
				paginaAtual = 1;
				break;
			}
		}
		primeiro();
	}
	
    public String getLocalizacao() {
        return paginaAtual+" de "+paginaTotal;
    }
    
    public int getPaginacao() {
        return paginacao;
    }  	

    public int getInicio() {
        return inicio;
    }

    public void setInicio(int inicio) {
        this.inicio = inicio;
    }

    public int getPaginaAtual() {
        return paginaAtual;
    }

    public void setPaginaAtual(int paginaAtual) {
        this.paginaAtual = paginaAtual;
    }

    public int getPaginaTotal() {
        return paginaTotal;
    }

    public void setPaginaTotal(int paginaTotal) {
        this.paginaTotal = paginaTotal;
    }    
}